#!/usr/bin/python
# -*- coding: utf-8 -*-

#-------------------------------------------------
#Create At: 2008-7-16 下午07:31:43 
#Create By: Fla.sam
#
#DESC: XiaMi Music Scanner
#
#-------------------------------------------------

from ObjectListView import ObjectListView, GroupListView, ColumnDefn, OLVEvent
from wx import xrc
from wx.lib import iewin
from wx.lib.wordwrap import wordwrap
import os
import scanner
import subprocess
import sys
import wx
import wx.lib.buttonpanel as bp
import wx.lib.delayedresult as delayedresult
import wx.media as media
import xiami_utils as xutils
import xiami_xrc

XIAMI_SITE = 'http://www.xiami.com/'
XS_SITE = XIAMI_SITE
XS_HELP_SITE = XIAMI_SITE
XSCANNER_VERSION = '0.1'

class OneObjMusicPopupMenu( xiami_xrc.xrcMusicListPopMenuOnOneObj ):
    
    def __init__( self, parent ):
        
        self.mainframe = parent
        xiami_xrc.xrcMusicListPopMenuOnOneObj.__init__( self )
        
class ManyObjMusicPopupMenu( xiami_xrc.xrcMusicListPopMenuOnManyObj ):
    
    def __init__( self ):
        xiami_xrc.xrcMusicListPopMenuOnManyObj.__init__( self )
        
class EditOneTagDialog( xiami_xrc.xrcMusicTagDialog ):
    
    def __init__( self, parent, obj ):
        
        self.mainframe = parent
        self.obj = obj
        print self.obj.filepath
        
        xiami_xrc.xrcMusicTagDialog.__init__( self, parent=self.mainframe )
        
        self.FilepathTextCtrl.SetValue(self.obj.filepath)
        
    def OnButton_CancelTagBtn(self, evt):
        # Replace with event handler code
        print "OnButton_CancelTagBtn()"
        self.Destroy()

class MusicListCtrl( GroupListView ):
    def __init__( self, parent, id ):
        
        self.mainframe = parent
        
        GroupListView.__init__( self, parent, id, style=wx.LC_REPORT | wx.NO_BORDER )

        #add my columns
        self.__MySetColumns()
        
        # init my group list ctrl 
        self.SetSortColumn( self.columns[4] )
        self.SetAlwaysGroupByColumn( self.columns[2] )
        
        self.SetEmptyListMsgFont( wx.Font( 18, wx.FONTFAMILY_MODERN, wx.NORMAL, wx.FONTWEIGHT_BOLD, 0, "" ) )
        self.SetEmptyListMsg( u'没有音乐? 如何生活? 赶快打开一个音乐文件夹吧...' )
        
        #should add check box ?
        #self.CreateCheckStateColumn()
        
        # change expand/collaps icon
        self.AddNamedImages( ObjectListView.NAME_EXPANDED_IMAGE, wx.Bitmap( 'resources/expand.png', wx.BITMAP_TYPE_PNG ) ) #@UndefinedVariable
        self.AddNamedImages( ObjectListView.NAME_COLLAPSED_IMAGE, wx.Bitmap( 'resources/collapse.png', wx.BITMAP_TYPE_PNG ) ) #@UndefinedVariable

        # all music file type icon
        self.AddNamedImages( 'track_type_mp3', wx.Bitmap( "resources/music_type_MP3.gif", wx.BITMAP_TYPE_GIF ) )
        self.AddNamedImages( 'track_type_ape', wx.Bitmap( "resources/music_type_APE.gif", wx.BITMAP_TYPE_GIF ) )
        self.AddNamedImages( 'track_type_apl', wx.Bitmap( "resources/music_type_APE.gif", wx.BITMAP_TYPE_GIF ) )
        self.AddNamedImages( 'track_type_flac', wx.Bitmap( "resources/music_type_FLAC.gif", wx.BITMAP_TYPE_GIF ) )
        
        self.many_obj_popupmenu = ManyObjMusicPopupMenu()
        self.one_obj_popupmenu = OneObjMusicPopupMenu(self.mainframe)
        
        #OK bind music List coontrol popup menu
        self.Bind( wx.EVT_CONTEXT_MENU, self.OnPopupMenu )
                
    def getTrackTypeImg( self, track ):
        if track.file_type == 'mp3':
            return 'track_type_mp3'
        elif track.file_type == 'ape':
            return 'track_type_ape'
        elif track.file_type == 'apl':
            return 'track_type_apl'
        elif track.file_type == 'flac':
            return 'track_type_flac'
        else:
            return - 1
        
    def _HandleColumnClick( self, evt ):
        """
        !! overwrite orginal method, The user has clicked on a column title
        """
        #wx.BeginBusyCursor()
        _busy_box = wx.BusyInfo( 'Please Wait...' )
        # If they click on a new column, we have to rebuild our groups
        if evt.GetColumn() != self.sortColumnIndex:
            self.groups = None

        ObjectListView._HandleColumnClick( self, evt ) #@UndefinedVariable
        _busy_box.Destroy()
        #wx.EndBusyCursor()
        
    def _DoExpandCollapse( self, groups, isExpanding ):
        """
        Do the real work of expanding/collapsing the given groups
        """
        #wx.BeginBusyCursor()
        _busy_box = wx.BusyInfo( 'Please Wait...' )
        # Cull groups that aren't going to change
        groups = [x for x in groups if x.isExpanded != isExpanding]
        if not groups:
            return

        # Let the world know that the given groups are about to be expanded/collapsed
        evt = OLVEvent.ExpandingCollapsingEvent( self, groups, isExpanding ) #@UndefinedVariable
        self.GetEventHandler().ProcessEvent( evt )
        if evt.IsVetoed():
            return

        for x in evt.groups:
            x.isExpanded = isExpanding
        self._BuildInnerList()
        self.RepopulateList()

        # Let the world know that the given groups have been expanded/collapsed
        evt = OLVEvent.ExpandedCollapsedEvent( self, evt.groups, isExpanding ) #@UndefinedVariable
        self.GetEventHandler().ProcessEvent( evt )
        _busy_box.Destroy()
        #wx.EndBusyCursor()
    
    def OnPopupMenu( self, evt ):
        
        _selected_item_count = self.GetSelectedItemCount()
        _selected_group = self.GetSelectedGroups()
        _selected_one_object = self.GetSelectedObject()
        _select_many_object = self.GetSelectedObjects()
        
        if _selected_item_count == 1 and _selected_group == [] and _selected_one_object != None and len( _select_many_object ) == 1:
            #show one popup menu
            self.PopupMenu( self.one_obj_popupmenu )
        elif  _selected_item_count > 1 and _selected_group == [] and _selected_one_object == None and len( _select_many_object ) > 0:
            #show many popup menu
            self.PopupMenu( self.many_obj_popupmenu )
        elif _selected_item_count == 1 and len( _selected_group ) == 1 and _selected_one_object == None and _select_many_object == []:
            #show group popup one menu
            pass
        elif _selected_item_count > 1 and len( _selected_group ) > 1 and _selected_one_object == None and _select_many_object == []:
            #show group popup many menu
            pass
        else:
            #No popup menu'
            pass
        
    def __MySetColumns( self ):
        self.SetColumns( [
                         ColumnDefn( u"标题", "left", 220, "title", imageGetter=self.getTrackTypeImg ),
                         ColumnDefn( u'专辑', "center", 200, "album", groupTitlePluralItems='%(title)s (%(count)d songs)' ),
                         ColumnDefn( u'艺术家', "center", 100, "artist" ),
                         ColumnDefn( u'音轨', "center", 55, "tracknumber" ),
                         ColumnDefn( u"流派", "center", 55, "genre" ),
                         ColumnDefn( u'发行时间', "center", 65, "date" ),
                         ColumnDefn( u'播放时长', "center", 65, "length" ),
                         ColumnDefn( u'文件尺寸', "center", 65, "size" ),
                         ColumnDefn( u'编码率/采样率/声道', "center", 130, "bitrate_samplerate_channel" ),
                         ColumnDefn( u'文件路径', "left", 800, "filepath" ),
                        ] )

    def InsertMusicList( self, tracks=None ):
        
        wx.BeginBusyCursor()
        _busy_box = wx.BusyInfo( 'please wait...' )
        if tracks == None:
            self.SetObjects( scanner.load_music_list() )
        else:
            self.SetObjects( tracks )
        _busy_box.Destroy()
        wx.EndBusyCursor()
        
class ScanMusicDirDialog( xiami_xrc.xrcScanMusicDirGaugeDialog ):
    
    def __init__( self, parent, scan_music_path ):
        
        app = wx.GetApp()
        self.mainframe = app.GetTopWindow()
        
        xiami_xrc.xrcScanMusicDirGaugeDialog.__init__( self, parent )
        
        self.CenterOnParent()
        self.scan_music_path = scan_music_path
        self.CurrentScanPathStaticCtrl.SetLabel( 'Scanning %s, please wait a few minute' % self.scan_music_path )
        
        # register a timer , let roll gauge ctrl
        self.pulse_scan_dlg_timer = wx.Timer( self )
        self.Bind( wx.EVT_TIMER, self.OnPulseScanDlg ) 
        self.pulse_scan_dlg_timer.Start( 100 )
        
        self.Bind( wx.EVT_CLOSE, self.handleClose )
        self.Bind( wx.EVT_BUTTON, self.handleAbort, self.AbortScanMusicBtn )
        
        self.abortEvent = delayedresult.AbortEvent()
        self.abortEvent.clear()
        
        delayedresult.startWorker( self._resultConsumer, self._resultProducer,
                                  wargs=( self.scan_music_path, self.abortEvent ) )
        
    def _resultProducer( self, path, abortEvent ):
        count = 0
        res = None
        while not abortEvent() and count < 1 :
            count += 1
            music_lists = scanner.get_file_list( path )
            music_tags = scanner.ReadTag( music_lists )
            for x in music_tags:
                pass
            res = music_tags.get_all_files_tag()
        return res
    
    def _resultConsumer( self, delayedResult ):
        
        try:
            result = delayedResult.get()
        except Exception, exc:
            wx.LogMessage( "Result for job raised exception: %s" % exc ) 
            return
        
        # output result
        wx.LogMessage( 'scan music directory ( %s ) finished, total found %s files' % ( self.scan_music_path, str( len( result ) ) ) )

        # close scan music dlg
        self.mainframe.MusicListPanelStatus( True )
        self.Destroy()
        
        #self.mainframe.music_list_ctrl.DeleteAllItems()
        self.mainframe.music_list_ctrl.InsertMusicList( result )
        
    def handleClose( self, event ):
        wx.LogMessage( "Close Scan Music job " )
        self.pulse_scan_dlg_timer.Stop()
        self.abortEvent.set()
        app = wx.GetApp()
        app.GetTopWindow().MusicListPanelStatus( True )
        self.Destroy()
        
    def handleAbort( self, event ): 
        """Abort the result computation."""
        wx.LogMessage( "Aborting Scan Music job" )
        self.pulse_scan_dlg_timer.Stop()
        self.abortEvent.set()
        app = wx.GetApp()
        app.GetTopWindow().MusicListPanelStatus( True )
        self.Destroy()
        
    def OnPulseScanDlg( self, evt ):
        self.ScanMusicGaugeCtrl.Pulse()
        self.Refresh()

class XiaMiFrame( xiami_xrc.xrcMainWindow ):
    
    def __init__( self, parent ):
        xiami_xrc.xrcMainWindow.__init__( self, parent )
        
        self.mainframe = xrc.XRCCTRL( self, 'MainWindow' )
        self.mainframe.SetFocus()
        
        #theme name
        self.theme_name = 'music_theme'
        
        #affirm all album is Expand
        self.expand_all = True
        
        # set log panel ctrl
        self.log_text_ctrl_id = xrc.XRCID( 'LogTextCtrl' )
        self.log_text_ctrl = xrc.XRCCTRL( self.mainframe, 'LogTextCtrl' )
        self.do_log = wx.LogTextCtrl( self.log_text_ctrl )
        wx.Log_SetActiveTarget( self.do_log )
        wx.LogMessage( '---- Start ----' )
        
        # replace unknow control 
        self.__replace_XiaMiWebWindowCtrl()
        self.__replace_WebButtonPanel()
        self.__replace_MusicListButtonPanel()
        self.__replace_MusicPlayerCtrl()
        self.__reaplce_XiaMiListCtrl()
        
        # ——- Fader Timer ——– ##
        self.amount = 5
        self.delta = 5
        self.mainframe.SetTransparent( self.amount )
        self.fadein_timer = wx.Timer( self, wx.ID_ANY )
        self.fadein_timer.Start( 1 )
        self.Bind( wx.EVT_TIMER, self.__fade_in )

        # bind replaced control
        
        # bind xiami web button panel event
        self.Bind( wx.EVT_BUTTON, self.OnWebHomeButton, id=self.xiami_home_button.GetId() )
        self.Bind( wx.EVT_BUTTON, self.OnWebBack, id=self.xiami_back_button.GetId() )
        self.Bind( wx.EVT_BUTTON, self.OnWebForward, id=self.xiami_forward_button.GetId() )
        self.Bind( wx.EVT_BUTTON, self.OnWebRefresh, id=self.xiami_refresh_button.GetId() )
        self.Bind( wx.EVT_BUTTON, self.OnWebStop, id=self.xiami_stop_button.GetId() )
        
        # bind music list button panel event
        self.Bind( wx.EVT_BUTTON, self.OnOpenMusicDirectoryButton, self.open_directory_button )
        self.Bind( wx.EVT_BUTTON, self.OnToggECButton, self.music_ec_button )
        
        # bind music list ctrl event
        self.Bind( wx.EVT_MENU, self.OnFindOneFile, self.music_list_ctrl.one_obj_popupmenu.FindFileMenu )
        self.Bind( wx.EVT_MENU, self.OnEditOneTagMenu, self.music_list_ctrl.one_obj_popupmenu.EditOneTagMenu )
        
        #FIXME: Not working, when can not back or forward disable button
        self.xiami_back_button.Bind( wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, self.xiami_back_button, self.xiami_back_button.GetId() )
        self.xiami_forward_button.Bind( wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, self.xiami_forward_button, self.xiami_forward_button.GetId() )
        
        
    def __theme_color( self, theme_name ):
        '''
        
        @param theme_name:
        '''
        
        #self.theme_list = {'music':'music_theme', 'default':'default_theme'}
        
        self.theme_color_music = {'base':wx.Color( 225, 250, 238 ), \
                            'select':wx.Color( 204, 76, 47 ), \
                            'cycle1':wx.Color( 169, 235, 221 ), \
                            'cycle2':wx.Color( 75, 214, 193 ), \
                            'font':wx.Color( 22, 28, 27 )}
        
        self.theme_color_default = {'base':wx.Color( 237, 230, 227 ), \
                              'select':wx.Color( 255, 255, 159 ), \
                              'cycle1':wx.Color( 167, 197, 217 ), \
                              'cycle2':wx.Color( 95, 160, 184 ), \
                              'font':wx.Color( 44, 65, 112 )}
        
        if hasattr( self, theme_name ):
            return getattr( self, theme_name )
        else:
            return self.theme_color_default
        
    def __fade_in( self, evt ):
        '''
        make top windows fade in 
        @param evt:
        '''
        self.amount += self.delta
        if self.amount >= 256:
            self.fadein_timer.Stop()
            evt.Skip()
        else:
            self.mainframe.SetTransparent( self.amount )
        
    def __set_button_panel_style( self, b_p ):
        '''
        set button panel style 
        @param b_p: botton panel name
        '''
    
        bpArt = getattr( b_p, 'GetBPArt' )()
        bpArt.SetColor( bp.BP_BUTTONTEXT_COLOR, wx.BLACK )
        bpArt.SetColor( bp.BP_GRADIENT_COLOR_FROM, wx.Color( 238, 238, 238 ) )
        bpArt.SetColor( bp.BP_GRADIENT_COLOR_TO, wx.Color( 254, 254, 254 ) )
        bpArt.SetColor( bp.BP_SELECTION_BRUSH_COLOR, wx.Color( 238, 238, 238 ) )
        bpArt.SetColor( bp.BP_SELECTION_PEN_COLOR, wx.Color( 179, 179, 179 ) )
        bpArt.SetColor( bp.BP_TEXT_COLOR, wx.Color( 151, 156, 156 ) )
        bpArt.SetColor( bp.BP_SEPARATOR_COLOR, wx.Color( 151, 156, 156 ) )
        bpArt.SetMetric( bp.BP_BORDER_SIZE, 1 )
    
    def __replace_XiaMiWebWindowCtrl( self ):

        self.web_id = xrc.XRCID( 'XiaMiWebWindowCtrl' )
        xiami_xrc.get_resources().AttachUnknownControl( 'XiaMiWebWindowCtrl', iewin.IEHtmlWindow( parent=self.mainframe, id=self.web_id ), self.mainframe )
        
        self.web = xrc.XRCCTRL( self.mainframe, 'XiaMiWebWindowCtrl' )
        wx.LogMessage( 'Load %s .' % XIAMI_SITE )
        self.web.LoadUrl( XIAMI_SITE )
        wx.LogMessage( 'Load %s done.' % XIAMI_SITE )
        self.web.AddEventSink( self )
        
    def __replace_MusicPlayerCtrl( self ):
        
        #load music player ctrl
        self.music_play_panel = xrc.XRCCTRL( self.MainContainerPanelCtrl, 'MusiPlayerPanelCtrl' )
        if sys.platform == 'win32':
            self.music_player = media.MediaCtrl( self.music_play_panel, szBackend=media.MEDIABACKEND_WMP10 )
        else:
            self.music_player = media.MediaCtrl( self.music_play_panel, szBackend=media.MEDIABACKEND_GSTREAMER )
        
#        print self.music_player.SetInitialSize()
#        print self.music_player.Load('c:/1.mp3')
#        print self.music_player.State
#        print self.music_player.GetVolume()
#        print self.music_player.SetVolume(100)
#        print self.music_player.Play()
#        print self.music_player.State

        self.music_player_button_panel_id = xrc.XRCID( 'MusicPlayerButtonPanelCtrl' )
        self.music_player_button_panel = xrc.XRCCTRL( self.music_play_panel, 'MusicPlayerButtonPanelCtrl' )

        self.music_player_button_panel_alignment = bp.BP_ALIGN_LEFT
        self.music_player_button_panel_style = bp.BP_GRADIENT_COLOR_TO | bp.BP_GRADIENT_COLOR_FROM | bp.BP_GRADIENT_HORIZONTAL | bp.BP_USE_GRADIENT
        
        xiami_xrc.get_resources().AttachUnknownControl( 'MusicPlayerButtonPanelCtrl', \
                                        bp.ButtonPanel( self.music_play_panel, self.music_player_button_panel_id, "", \
                                        style=self.music_player_button_panel_style, \
                                        alignment=self.music_player_button_panel_alignment ), self.music_play_panel )

        self.music_player_button_panel = xrc.XRCCTRL( self.music_play_panel, 'MusicPlayerButtonPanelCtrl' )
        
        # now add play button
        self.music_play_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/music_play.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Play Music''', longHelp='''Play Current Music''' )
        self.music_play_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_player_button_panel.AddButton( self.music_play_button )
        
        self.music_pause_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/music_pause.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Pause Music''', longHelp='''Pause Current Music''' )
        self.music_pause_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_player_button_panel.AddButton( self.music_pause_button )
        
        self.music_stop_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/music_stop.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Stop Music''', longHelp='''Stop Current Music''' )
        self.music_stop_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_player_button_panel.AddButton( self.music_stop_button )
        
        self.music_rewind_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/music_rewind.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Rewind Music''', longHelp='''Rewind Last Music''' )
        self.music_rewind_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_player_button_panel.AddButton( self.music_rewind_button )
        
        self.music_forward_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/music_forward.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Forward Music''', longHelp='''Forward Next Music''' )
        self.music_forward_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_player_button_panel.AddButton( self.music_forward_button )
        
        self.music_player_button_panel.AddSeparator()
        
        #add playlist ctrl
        self.music_player_button_panel.AddControl( bp.ButtonPanelText( self.music_player_button_panel, 'PlayList' ) )
        self.music_play_index_list_ctrl = wx.Choice( self.music_player_button_panel, wx.NewId(), size=( 150, - 1 ), choices=['default'] )
        self.music_player_button_panel.AddControl( self.music_play_index_list_ctrl )
        self.music_play_index_list_del_button = bp.ButtonInfo( self.music_player_button_panel, wx.NewId(), wx.Bitmap( "resources/delete.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Delete Playlist''', longHelp='''Delete Current Playlist''' )
        self.music_player_button_panel.AddButton( self.music_play_index_list_del_button )
        
        # do button panel layout
        self.__set_button_panel_style( self.music_player_button_panel )
        self.music_player_button_panel.DoLayout()

    def __replace_MusicListButtonPanel( self ):
        
        self.music_list_button_panel_id = xrc.XRCID( 'MusicListButtonPanelCtrl' )
        self.music_list_button_panel = xrc.XRCCTRL( self.mainframe, 'MusicListButtonPanelCtrl' )
        
        self.music_list_button_panel_alignment = bp.BP_ALIGN_LEFT
        self.music_list_button_panel_style = bp.BP_GRADIENT_COLOR_TO | bp.BP_GRADIENT_COLOR_FROM | bp.BP_GRADIENT_HORIZONTAL | bp.BP_USE_GRADIENT
        
        xiami_xrc.get_resources().AttachUnknownControl( 'MusicListButtonPanelCtrl', \
                                        bp.ButtonPanel( self.mainframe, self.music_list_button_panel_id, "", \
                                        style=self.music_list_button_panel_style, \
                                        alignment=self.music_list_button_panel_alignment ), self.mainframe )

        self.music_list_button_panel = xrc.XRCCTRL( self.mainframe, 'MusicListButtonPanelCtrl' )
        
        # add open music directory button
        self.open_directory_button = bp.ButtonInfo( self.music_list_button_panel, wx.NewId(), wx.Bitmap( "resources/open_music_button.png", wx.BITMAP_TYPE_PNG ), text='Open Music Directory' )
        self.open_directory_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_list_button_panel.AddButton( self.open_directory_button )
        
#        #add rescan music button
#        self.music_reload_button = bp.ButtonInfo( self.music_list_button_panel, wx.NewId(), wx.Bitmap( "resources/reload_music_button.png", wx.BITMAP_TYPE_PNG ), text='Rescan Music' )
#        self.music_reload_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
#        self.music_list_button_panel.AddButton( self.music_reload_button )
#        
#        self.music_list_button_panel.AddSeparator()
        
        #add expand/collaps music album button
        self.music_ec_button = bp.ButtonInfo( self.music_list_button_panel, wx.NewId(), wx.Bitmap( "resources/e_c_album.png", wx.BITMAP_TYPE_PNG ), text='Expand/Collapse All Album' )
        self.music_ec_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.music_list_button_panel.AddButton( self.music_ec_button )
        
        #add music list filter ctrl
        #self.music_list_filter_ctrl = wx.SearchCtrl( self.music_list_button_panel, id=wx.NewId(), size=( 150, - 1 ), style=wx.TE_PROCESS_ENTER )
        #self.music_list_button_panel.AddControl( self.music_list_filter_ctrl )
        #self.music_list_filter_ctrl.SetDescriptiveText( 'Filter Music List' )
        #self.music_list_filter_ctrl.ShowCancelButton( - 1 )
        #self.music_list_filter_ctrl.ShowSearchButton( - 1 )
        
        # change search ctrl icon
        #self.music_list_filter_ctrl.SetSearchBitmap(wx.Bitmap( "resources/filter.png", wx.BITMAP_TYPE_PNG ))
        #self.music_list_filter_ctrl.SetCancelBitmap(wx.Bitmap( "resources/cancel.png", wx.BITMAP_TYPE_PNG ))
        
        # do button panel layout
        self.__set_button_panel_style( self.music_list_button_panel )
        self.music_list_button_panel.DoLayout()
        
    def __replace_WebButtonPanel( self ):
        
        self.web_button_panel_id = xrc.XRCID( 'XiaMiWebButtonPanelCtrl' )
        self.web_button_panel = xrc.XRCCTRL( self.mainframe, 'XiaMiWebButtonPanelCtrl' )
        
        self.web_button_panel_alignment = bp.BP_ALIGN_LEFT
        self.web_button_panel_style = bp.BP_GRADIENT_COLOR_TO | bp.BP_GRADIENT_COLOR_FROM | bp.BP_GRADIENT_HORIZONTAL | bp.BP_USE_GRADIENT
        
        xiami_xrc.get_resources().AttachUnknownControl( 'XiaMiWebButtonPanelCtrl', \
                                        bp.ButtonPanel( self.mainframe, self.web_button_panel_id, "", \
                                        style=self.web_button_panel_style, \
                                        alignment=self.web_button_panel_alignment ), self.mainframe )
        
        
        self.web_button_panel = xrc.XRCCTRL( self.mainframe, 'XiaMiWebButtonPanelCtrl' )
        
        # add xiami home button
        self.xiami_home_button = bp.ButtonInfo( self.web_button_panel, wx.NewId(), wx.Bitmap( "resources/XiaMiHome.png", wx.BITMAP_TYPE_PNG ), text='XiaMi', shortHelp='''XiaMi's Home''', longHelp='''Go to XiaMi's home''' )
        self.xiami_home_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.web_button_panel.AddButton( self.xiami_home_button )
        
        # add xiami back button
        self.xiami_back_button = bp.ButtonInfo( self.web_button_panel, wx.NewId(), wx.Bitmap( "resources/web_back.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Back''', longHelp='''Back to last page''' )
        self.xiami_back_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.web_button_panel.AddButton( self.xiami_back_button )
        
        # add xiami forward button
        self.xiami_forward_button = bp.ButtonInfo( self.web_button_panel, wx.NewId(), wx.Bitmap( "resources/web_forward.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Forward''', longHelp='''Forward to next page''' )
        self.xiami_forward_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.web_button_panel.AddButton( self.xiami_forward_button )
        
        # add xiami refresh button
        self.xiami_refresh_button = bp.ButtonInfo( self.web_button_panel, wx.NewId(), wx.Bitmap( "resources/web_refresh.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Refresh''', longHelp='''Refresh current page''' )
        self.xiami_refresh_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.web_button_panel.AddButton( self.xiami_refresh_button )
        
        # add xiami stop button
        self.xiami_stop_button = bp.ButtonInfo( self.web_button_panel, wx.NewId(), wx.Bitmap( "resources/web_stop.png", wx.BITMAP_TYPE_PNG ), text='', shortHelp='''Stop''', longHelp='''Stop current current page loading''' )
        self.xiami_stop_button.SetTextAlignment( bp.BP_BUTTONTEXT_ALIGN_RIGHT )
        self.web_button_panel.AddButton( self.xiami_stop_button )
        
        # do button panel layout
        self.__set_button_panel_style( self.web_button_panel )
        self.web_button_panel.DoLayout()
        
    def __reaplce_XiaMiListCtrl( self ):
        
        self.music_list_ctrl_id = xrc.XRCID( 'XiaMiListCtrl' )
        self.music_list_ctrl = xrc.XRCCTRL( self.mainframe, 'XiaMiListCtrl' )
        
        xiami_xrc.get_resources().AttachUnknownControl( 'XiaMiListCtrl', \
                                        MusicListCtrl( self.mainframe, self.music_list_ctrl_id ), self.mainframe )
        
        self.music_list_ctrl = xrc.XRCCTRL( self.mainframe, 'XiaMiListCtrl' )
        self.music_list_ctrl.Refresh()
        
    def OnFindOneFile( self, evt ):
        _obj = self.music_list_ctrl.GetSelectedObject()
        subprocess.Popen( ['explorer.exe', '/select,', r'%s' % _obj.filepath.encode( 'gbk' ) ] )
        
    def OnEditOneTagMenu( self, evt ):
        _obj = self.music_list_ctrl.GetSelectedObject()
        self.one_tag_dialog = EditOneTagDialog( self.mainframe, _obj )
        self.one_tag_dialog.ShowModal()
        
    def OnWebHomeButton( self, evt ):
        self.web.Stop()
        self.web.LoadUrl( XIAMI_SITE )
        evt.Skip()
        
    def OnWebBack( self, evt ):
        self.web.GoBack()
        evt.Skip()
        
    def OnWebForward( self, evt ):
        self.web.GoForward()
        evt.Skip()
        
    def OnWebStop( self, evt ):
        self.web.Stop()
        evt.Skip()
        
    def OnWebRefresh( self, evt ):
        self.web.RefreshPage()
        evt.Skip()
        
    def OnCheckCanGoBack( self, evt ):
        self.xiami_back_button.Enable( self.web.CanGoBack() )
        evt.Skip()
        
    def OnCheckCanGoForward( self, evt ):
        self.xiami_forward_button.Enable( self.web.CanGoForward() )
        evt.Skip()
        
    def OnMenu_ExitMenu( self, evt ):
        self.Destroy()
        
    def OnMenu_HelpMenu( self, evt ):
        import webbrowser
        webbrowser.open_new_tab( XS_HELP_SITE )
        del( webbrowser )
        
    def OnMenu_AboutMenu( self, evt ):
        info = wx.AboutDialogInfo()
        info.Name = "XiaMi Music Scanner"
        info.Version = XSCANNER_VERSION
        info.Copyright = "(C) 2008 fla.sam"
        info.Description = wordwrap( 
            u'''虾米是一个与众不同的平台，在这里你可以和朋友一起寻找、分享你们喜爱的音乐；你还可以利用虾米来上传、下载没有DRM保护的高品质MP3音乐，并且在上传、下载过程中赚点零花钱''',
            350, wx.ClientDC( self ) )
        info.WebSite = ( XS_SITE, "访问XiaMi网站" )
        info.Developers = [ "fla.sam Programmer", ]
        info.License = wordwrap( '', 500, wx.ClientDC( self ) )

        # Then we call wx.AboutBox giving it that info object
        wx.AboutBox( info )
        
    def MusicListPanelStatus( self, s ):
        
        getattr( self, 'MusicListPanel' ).Enable( s )
        getattr( self, 'MusiPlayerPanelCtrl' ).Enable( s )
                    
    def OnOpenMusicDirectoryButton( self, evt ):
        self.opendir_dlg = wx.DirDialog( self, "Choose a directory:", \
                          style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST )
        if self.opendir_dlg.ShowModal() == wx.ID_OK:
            
            #read scan directory path
            self.music_directory_path = self.opendir_dlg.GetPath()
            
            wx.LogMessage( u'Scanning Music Directory: %s.' % self.music_directory_path )
            
            # when scan music disable music list panel
            self.MusicListPanelStatus( False )

            # show ScanMusicDirDialog
            self.scan_dlg = ScanMusicDirDialog( self.mainframe, self.music_directory_path )
            #self.scan_dlg.CurrentScanPathStaticCtrl.SetLabel( 'Scanning %s' % self.music_directory_path )
            self.scan_dlg.Show()

        # Only destroy a dialog after you're done with it.
        self.opendir_dlg.Destroy()
        
    def OnToggECButton( self, evt ):
        #wx.BeginBusyCursor()
        _busy_box = wx.BusyInfo( 'Please Wait...' )
        if self.expand_all:
            self.expand_all = False
            self.music_list_ctrl.CollapseAll()
        else:
            self.expand_all = True
            self.music_list_ctrl.ExpandAll()
        _busy_box.Destroy()
        #wx.EndBusyCursor()
        
            
    
        
class XiaMiApp( wx.App ):
    
    def __init__( self ):
        '''Constructor.'''
        wx.App.__init__( self, False )
        
    def OnInit( self ):
        '''Sets everything up'''
        # set up the main frame of the app
        self.SetAppName( 'XiaMi Music Scanner' )
        self.mainframe = XiaMiFrame( None )
        self.SetTopWindow( self.mainframe )
        self.mainframe.SetMinSize( ( 1024, 700 ) )
        
        # fix ie windows, size
        self.mainframe.SetSize( ( 1024, 600 ) )
        self.mainframe.Show()
        return True
    
def main():
    xiami_app = XiaMiApp()
    xiami_app.MainLoop()

if __name__ == '__main__':
    main()